﻿using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

using Common.Base;

using CommunicationLibrary.TransportData;

using GameCommon.ManagerInterfaces;

using GameGraphics.Helper;

using GameNetwork.Network;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace GameGraphics.Components
{
    [DebuggerDisplay("BoardTile at {Dimension.X}/{Dimension.Y} ({GridPosition.X}/{GridPosition.Y})")]
    internal class BoardTile : Texture
    {
        public BoardTile(string id, Texture2D texture)
            : base(id, texture)
        {
            this.Layer = 1;
            this.FarmerRoutes = new List<Route>();
            this.MilitiaRoutes = new List<Route>();
        }

        public Position GridPosition { get; set; }

        public Hitpoints HitPoints { get; set; }

        public List<Route> MilitiaRoutes { get; set; }

        public List<Route> FarmerRoutes { get; set; }

        public Highlight Highlight { get; set; }

        public Building Building { get; set; }

        public bool IsSelected { get; private set; }

        public bool IsOwned { get; private set; }

        public bool IsFighterMode { get; private set; }

        public bool IsFarmerMode { get; private set; }

        public Position TileCenterPosition
        {
            get
            {
                var x = this.Dimension.X + (this.Dimension.Width / 2);
                var y = this.Dimension.Y + (this.Dimension.Height / 2);
                return new Position(x, y);
            }
        }

        public void InitializeHighlight(Texture2D texture)
        {
            this.Highlight = new Highlight();
            this.Highlight.Dimension.Position = this.Dimension.Position;
            this.Highlight.Layer = this.Layer + 1;
        }

        public override void Draw(IDrawingManager manager, GameTime gameTime)
        {
            base.Draw(manager, gameTime);

            if (this.IsFighterMode && this.MilitiaRoutes.Count > 0)
            {
                foreach (var route in this.MilitiaRoutes)
                {
                    route.Draw(manager, gameTime);
                }
            }

            if (this.IsFarmerMode && this.FarmerRoutes.Count > 0)
            {
                foreach (var route in this.FarmerRoutes)
                {
                    route.Draw(manager, gameTime);
                }
            }

            if (this.HitPoints != null)
            {
                this.HitPoints.Draw(manager, gameTime);
            }

            if (this.Highlight != null)
            {
                this.Highlight.Draw(manager);
            }

            if (this.Building != null)
            {
                this.Building.Draw(manager);
            }
        }

        public override string ToString()
        {
            return string.Format("{0}/{1}", this.GridPosition.X, this.GridPosition.Y);
        }

        public void Update(int playerId, Tile tile)
        {
            this.IsOwned = tile.Owner.Identifier == playerId;

            this.UpdateHighlight();
            this.UpdateHitPoints(tile);
            this.UpdateBuilding(tile);
            this.UpdateRoutes(tile);
        }

        public void AddRoute(BoardTile endTile, RouteTypeEnum routeType)
        {
            if (routeType == RouteTypeEnum.Farmer)
            {
                this.FarmerRoutes.Add(BoardBuilder.GetRoute(this, endTile, routeType, this.Dimension));
            }
            else
            {
                this.MilitiaRoutes.Add(BoardBuilder.GetRoute(this, endTile, routeType, this.Dimension));
            }
        }

        public void RemoveRoute(Position tileEndPosition, RouteTypeEnum routeType)
        {
            if (routeType == RouteTypeEnum.Farmer)
            {
                this.FarmerRoutes.RemoveAll(x => x.EndArrayPosition.Equals(tileEndPosition));
            }
            else
            {
                this.MilitiaRoutes.RemoveAll(x => x.EndArrayPosition.Equals(tileEndPosition));
            }
        }

        public void ShowFighterRoutes()
        {
            this.IsFarmerMode = false;
            this.IsFighterMode = true;
        }

        public void ShowFarmerRoutes()
        {
            this.IsFarmerMode = true;
            this.IsFighterMode = false;
        }

        public void Select()
        {
            this.IsSelected = true;
        }

        public void Deselect()
        {
            this.IsSelected = false;
        }

        public void Conquer()
        {
            this.IsOwned = true;
        }

        public void Lose()
        {
            this.IsOwned = false;
        }

        private void UpdateRoutes(Tile tile)
        {
            if (this.MilitiaRoutes.Any())
            {
                this.UpdateMilitiaRoutes(tile);
            }

            if (this.FarmerRoutes.Any())
            {
                this.UpdateFarmerRoutes(tile);
            }
        }

        private void UpdateFarmerRoutes(Tile tile)
        {
            foreach (var farmerRoute in tile.FarmerRoutes)
            {
                var r = this.FarmerRoutes.FirstOrDefault(x => x.EndArrayPosition.Equals(farmerRoute.EndTile.Position));
                if (r != null)
                {
                    r.Update(farmerRoute.UnitProgressList);
                }
            }
        }

        private void UpdateMilitiaRoutes(Tile tile)
        {
            foreach (var militiaRoute in tile.MilitiaRoutes)
            {
                var r = this.MilitiaRoutes.FirstOrDefault(x => x.EndArrayPosition.Equals(militiaRoute.EndTile.Position));
                if (r != null)
                {
                    r.Update(militiaRoute.UnitProgressList);
                }
            }
        }

        private void UpdateHitPoints(Tile tile)
        {
            if (this.HitPoints != null)
            {
                this.HitPoints.Update(tile);
            }
        }

        private void UpdateBuilding(Tile tile)
        {
            if (tile.Building == null)
            {
                return;
            }

            if (this.Building == null || tile.Building.BuildingType != this.Building.BuildingType)
            {
                this.Building = new Building(tile.Building.BuildingType, this.Dimension);
            }

            this.Building.SetProgress(tile.Building.CurrentProgress);
        }

        private void UpdateHighlight()
        {
            if (this.Highlight == null)
            {
                return;
            }

            this.Highlight.Update(this.IsOwned, this.IsSelected, this.HitBox.IsMouseOver);
        }
    }
}